package com.boe.common.util.freemark;

import com.boe.common.enums.CodeGenerateTypeEnum;
import com.boe.common.model.BaseFreemarkerModel;
import com.boe.common.util.ScopeUtil;
import freemarker.cache.ClassTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import lombok.*;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Locale;

public class FreemarkerUtil {

    /**
     * 传入需要转义的字符串进行转义
     */

    public static String escapeString(String originStr) {
        return originStr.replace("井", "\\#").replace("￥", "\\$");
    }

    /**
     * freemarker config
     */
    private static Configuration getFreemarkerConfig() {
        var ret = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);

        //freemarkerConfig.setDirectoryForTemplateLoading(new File(templatePath, "templates/code-generator"));
        ret.setNumberFormat("#");
        ret.setClassicCompatible(true);
        ret.setDefaultEncoding("UTF-8");
        ret.setLocale(Locale.CHINA);
        ret.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);

        ret.setClassForTemplateLoading(FreemarkerUtil.class, "/");
        ret.setTemplateLoader(
                new ClassTemplateLoader(
                        FreemarkerUtil.class,
                        "/"
                )
        );

        return ret;
    }

    /**
     * process Template Into String
     */

    @SneakyThrows
    private static String processTemplate(Template template, BaseFreemarkerModel params) {
        var result = new StringWriter();
        template.process(params, result);
        return result.toString();
    }


    /**
     * process String
     *
     * @return
     * @throws IOException
     * @throws TemplateException
     */


    @SneakyThrows
    public static String process(CodeGenerateTypeEnum action, BaseFreemarkerModel model) {
        var config = getFreemarkerConfig();


        var templateName = "";
        switch (action) {
            case CONTROLLER:
                templateName = "freemarker/controller.ftl";
                break;
            case ADD_VO:
                templateName = "freemarker/vo/add_vo.ftl";
                break;
            case UPDATE_VO:
                templateName = "freemarker/vo/update_vo.ftl";
                break;
            case REQUEST_VO:
                templateName = "freemarker/vo/request_vo.ftl";
                break;
            case RESPONSE_VO:
                templateName = "freemarker/vo/response_vo.ftl";
                break;
            case MAPPER:
                templateName = "freemarker/mybatisplus_mapper.ftl";
                break;
            case INTERFACE:
                templateName = "freemarker/interface_service.ftl";
                break;
            case IMPL:
                templateName = "freemarker/impl_service.ftl";
                break;
            case JPA_ENTITY:
                templateName = "freemarker/entity/jpa-entity.ftl";
                break;
            case MYBATIS_PLUS_ENTITY:
                templateName = "freemarker/entity/mybatisplus-entity.ftl";
                break;
            default:
                break;
        }
        Template template = config.getTemplate(templateName);

        return ScopeUtil.usingScope(new ContextMapScope(model), () -> escapeString(processTemplate(template, model)));
    }
}

